package com.sunrise.estoque.servico;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import lombok.Getter;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sunrise.configuracoes.repositorio.iface.ParcelaDao;
import com.sunrise.estoque.bo.EstoqueBO;
import com.sunrise.estoque.repositorio.iface.EstoqueDao;
import com.sunrise.estoque.repositorio.iface.HistoricoVendaDao;
import com.sunrise.estoque.repositorio.iface.PagamentoDao;
import com.sunrise.estoque.repositorio.iface.ProdutoDao;
import com.sunrise.estoque.repositorio.iface.VendaDao;
import com.sunrise.estoque.repositorio.iface.VendaProdutoDao;
import com.sunrise.generico.entidade.Estoque;
import com.sunrise.generico.entidade.HistoricoVenda;
import com.sunrise.generico.entidade.Parcela;
import com.sunrise.generico.entidade.Produto;
import com.sunrise.generico.entidade.Venda;
import com.sunrise.generico.entidade.VendaProduto;
import com.sunrise.generico.enums.Status;
import com.sunrise.generico.enums.TipoVenda;
import com.sunrise.generico.visao.Filtro;

@Service
@Transactional(readOnly = true)
public class ManterVendaService {

	@Resource(name = "vendaDaoImpl")
	@Getter
	private VendaDao vendaDAO;

	@Resource(name = "produtoDaoImpl")
	@Getter
	private ProdutoDao produtoDAO;

	@Resource(name = "parcelaDaoImpl")
	@Getter
	private ParcelaDao parcelaDAO;

	@Resource(name = "estoqueDaoImpl")
	@Getter
	private EstoqueDao estoqueDAO;

	@Resource(name = "pagamentoDaoImpl")
	@Getter
	private PagamentoDao pagamentoDAO;

	@Resource(name = "vendaProdutoDaoImpl")
	@Getter
	private VendaProdutoDao vendaProdutoDAO;

	@Resource(name = "historicoVendaDaoImpl")
	@Getter
	private HistoricoVendaDao historicoVendaDAO;

	public Collection<Venda> buscarPorFiltros(Filtro filtro) {
		Collection<Venda> vendas = getVendaDAO().buscarPorFiltros(filtro);
		for (Venda venda : vendas) {
			venda.getVendaProdutos().size();
		}
		return vendas;
	}

	public List<Produto> buscarProdutoPorNome(String nome) {
		return getProdutoDAO().listarPorNome(nome);
	}

	public List<Produto> buscarProdutosPorCodigoNome(Produto produtoFiltro) {
		return getProdutoDAO().buscarProdutosPorCodigoOuNome(produtoFiltro);
	}

	public Collection<? extends VendaProduto> adicionarProtudosSelecionados(Produto[] produtosSelecionados, Venda venda) {
		Collection<VendaProduto> vendaProdutos = new ArrayList<VendaProduto>();
		for (Produto prod : produtosSelecionados) {
			Boolean inserido = false;
			if (!venda.getVendaProdutos().isEmpty()) {
				for (VendaProduto vProduto : venda.getVendaProdutos()) {
					if (vProduto.getProduto().getId().equals(prod.getId())) {
						inserido = true;
					}
				}
			}
			if (!inserido) {
				VendaProduto vendaProduto = new VendaProduto();
				vendaProduto.setProduto(prod);
				vendaProduto.setQuantidade(new BigDecimal(1));
				vendaProduto.setVenda(venda);
				vendaProduto.setTotal(prod.getPrecoVenda());
				vendaProdutos.add(vendaProduto);
			}
		}

		return vendaProdutos;
	}

	public Collection<Parcela> listarParcelas() {
		return getParcelaDAO().listarAtivoOrdenado();
	}

	@Transactional(readOnly = false)
	public void salvarVenda(Venda entidade) {
		for (VendaProduto vProduto : entidade.getVendaProdutos()) {
			getVendaProdutoDAO().inserir(vProduto);
		}

		if (entidade.getTipoVenda().equals(TipoVenda.VENDA)) {
			atualizarEstoqueRealizarVenda(entidade);
		}
		if (entidade.getTipoVenda().equals(TipoVenda.RESERVA)) {
			atualizarEstoqueRealizarReserva(entidade);
		}
		entidade.setStatusVenda(Status.REALIZADO);
		getPagamentoDAO().inserir(entidade.getPagamento());
		getVendaDAO().inserir(entidade);
		inserirHistorico(entidade, Status.REALIZADO);

	}

	private void inserirHistorico(Venda entidade, Status status) {
		HistoricoVenda hVenda = new HistoricoVenda();
		hVenda.setData(new Date());
		hVenda.setStatusVenda(status);
		hVenda.setVenda(entidade);
		getHistoricoVendaDAO().inserir(hVenda);

	}

	public void atualizarEstoqueRealizarVenda(Venda entidade) {
		for (VendaProduto vProduto : entidade.getVendaProdutos()) {
			Estoque estoqueFilial = null;
			for (Estoque estoque : vProduto.getProduto().getEstoque()) {
				if (estoque.getFilial().getId().equals(entidade.getFilial().getId())) {
					estoqueFilial = estoque;
				}
			}
			getVendaProdutoDAO().inserir(vProduto);
			EstoqueBO.removerEstoque(estoqueFilial, vProduto.getQuantidade());
			getEstoqueDAO().alterar(estoqueFilial);
		}

	}

	public void atualizarEstoqueRealizarReserva(Venda entidade) {

		for (VendaProduto vProduto : entidade.getVendaProdutos()) {
			Estoque estoqueFilial = null;
			for (Estoque estoque : vProduto.getProduto().getEstoque()) {
				if (estoque.getFilial().getId().equals(entidade.getFilial().getId())) {
					estoqueFilial = estoque;
				}
			}

			getVendaProdutoDAO().inserir(vProduto);
			EstoqueBO.reservarEstoque(estoqueFilial, vProduto.getQuantidade());
			if (estoqueFilial.getQuantidadeReservada() == null) {
				estoqueFilial.setQuantidadeReservada(vProduto.getQuantidade());
			} else {
				estoqueFilial.setQuantidadeReservada(estoqueFilial.getQuantidadeReservada().add(
						vProduto.getQuantidade()));

			}
			getEstoqueDAO().alterar(estoqueFilial);
		}

	}

	public Collection<Venda> listarOrdenadoVendaProdutos(Venda entidade) {
		Collection<Venda> vendas = getVendaDAO().listarOrdenado();
		for (Venda venda : vendas) {
			venda.getVendaProdutos().size();
		}
		return vendas;
	}

	@Transactional(readOnly = false)
	public void cancelarVenda(Venda entidade) {
		atualizarEstoqueCancelarVenda(entidade);
		entidade.setStatusVenda(Status.CANCELADO);
		inserirHistorico(entidade, Status.CANCELADO);
		getVendaDAO().alterar(entidade);
	}

	private void atualizarEstoqueCancelarVenda(Venda entidade) {
		for (VendaProduto vp : entidade.getVendaProdutos()) {
			
			Estoque estoqueFilial = null;
			for (Estoque estoque : vp.getProduto().getEstoque()) {
				if (estoque.getFilial().getId().equals(entidade.getFilial().getId())) {
					estoqueFilial = estoque;
				}
			}
			
			EstoqueBO.adicionarEstoque(estoqueFilial, vp.getQuantidade());
			getEstoqueDAO().alterar(estoqueFilial);
		}

	}

	public List<Produto> buscarProdutosPorNome(String nome) {
		return getProdutoDAO().listarPorNome(nome);
	}

}